﻿///////////////////////////////////////////////////////////////////////////////
//
//  This source is part of the  "Managed Task Framework.NET Runtime"  (MTF.NET Runtime).
//
//
//  Copyright (c) 2011, Multicore Consulting Limited (UK)
//  All rights reserved.
//  http://www.multicoreconsulting.co.uk
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions
//  are met:
//
//  -  Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//  -  Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in
//     the documentation and/or other materials provided with the
//     distribution.
//  -  Neither the name of Multicore Consulting Limited nor the names of
//     its contributors may be used to endorse or promote products
//     derived from this software without specific prior written
//     permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//  POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;

namespace MTFOrg.MTF.MTFRuntime
{
    /// <summary>
    /// Represents a list of connections.
    /// </summary>
    public class ConnectionList : IOrderedGroup<IConnection>
    {
        // Internal
        protected List<IConnection> m_Connections;

        /// <summary>
        /// Default constructor.
        /// </summary>
        public ConnectionList()
        {
            m_Connections = new List<IConnection>();
        }

        /// <summary>
        /// Creates and adds a new connection to the connection list.
        /// </summary>
        /// <param name="parentTask">Parent task for the connection</param>
        /// <param name="sourceConnectionPoint">Source connection point</param>
        /// <param name="targetConnectionDescriptors">Descriptors for targets to connect to</param>
        /// <param name="requireConnect">Whether the connection must be made</param>
        public void Add(ITask parentTask, IConnectionPoint sourceConnectionPoint, ConnectionDescriptorGroup targetConnectionDescriptors, bool requireConnect)
        {
            if (targetConnectionDescriptors == null || targetConnectionDescriptors.Count == 0)
            {
                if (requireConnect) throw new ConnectionPointNotConnectedException();
            }
            else
            {
                foreach (ConnectionDescriptor targetConnectionDescriptor in targetConnectionDescriptors)
                    m_Connections.Add(new Connection(
                        parentTask,
                        sourceConnectionPoint, 
                        targetConnectionDescriptor.SourceOrder,
                        targetConnectionDescriptor.TargetConnectionPoint,
                        targetConnectionDescriptor.TargetOrder,
                        targetConnectionDescriptor.ConnectionProperties));
            }
        }

        /// <summary>
        /// Adds a pre-existing connection to the connection list ordered by source index.
        /// </summary>
        /// <param name="connection">Connection to add</param>
        public void Add(IConnection connection)
        {
            m_Connections.Add(connection);
        }

        /// <summary>
        /// Inserts a pre-existing connection at the specified index.
        /// </summary>
        /// <param name="index">Index to insert connection at</param>
        /// <param name="connection">Connetion to insert</param>
        public void Insert(int index, IConnection connection)
        {
            m_Connections.Insert(index, connection);
        }

        /// <summary>
        /// Adds a pre-existing connection to the connection list ordered by source index.
        /// </summary>
        /// <param name="connection">Connection to add</param>
        public void AddSourceOrdered(IConnection connection)
        {
            int i;
            for (i = 0; i < m_Connections.Count; i++)
                if (connection.SourceOrder < m_Connections[i].SourceOrder)
                    break;

            m_Connections.Insert(i, connection);
        }

        /// <summary>
        /// Adds a pre-existing connection to the connection list ordered by target index.
        /// </summary>
        /// <param name="connection">Connection to add</param>
        public void AddTargetOrdered(IConnection connection)
        {
            int i;
            for (i = 0; i < m_Connections.Count; i++)
                if (connection.TargetOrder < m_Connections[i].TargetOrder)
                    break;

            m_Connections.Insert(i, connection);
        }

        /// <summary>
        /// Gets an enumerator for this collection.
        /// </summary>
        /// <returns>Enumerator for the connection collection</returns>
        public IEnumerator GetEnumerator()
        {
            return m_Connections.GetEnumerator();
        }

        /// <summary>
        /// Gets the connection at the specified index.
        /// </summary>
        /// <param name="index">Index to retrieve element from</param>
        /// <returns>Element at specified index</returns>
        public IConnection this[int index]
        {
            get
            {
                return m_Connections[index];
            }
        }

        /// <summary>
        /// Gets the number of connections in the group.
        /// </summary>
        public int Count
        {
            get
            {
                return m_Connections.Count;
            }
        }

    }
}